/**
 * 登录认证相关的API服务
 * 提供所有登录、注册、验证码等相关的接口调用
 */

import {
  ApiResponse,
  SendSmsRequest,
  SmsLoginRequest,
  SmsLoginResponse,
  LoginRequest,
  LoginResponse,
  SetPasswordRequest,
  CheckUsernameResponse,
  CheckPhoneResponse,
  SmsType
} from '../types/auth';

// ============= 基础配置 =============

/**
 * API基础URL
 */
const API_BASE_URL = '/api/auth';

/**
 * 请求超时时间(毫秒)
 */
const REQUEST_TIMEOUT = 10000;

/**
 * Cookie名称常量
 */
const COOKIE_NAMES = {
  ACCESS_TOKEN: 'ACCESS_TOKEN',
  REFRESH_TOKEN: 'REFRESH_TOKEN'
} as const;

// ============= Cookie工具函数 =============

/**
 * 获取Cookie值
 * @param name Cookie名称
 * @returns Cookie值或null
 */
function getCookie(name: string): string | null {
  try {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) {
      const cookieValue = parts.pop()?.split(';').shift();
      return cookieValue || null;
    }
    return null;
  } catch (error) {
    console.error('获取Cookie失败:', error);
    return null;
  }
}

/**
 * 设置Cookie
 * @param name Cookie名称
 * @param value Cookie值
 * @param options Cookie选项
 */
export function setCookie(name: string, value: string, options: {
  expires?: Date;
  maxAge?: number;
  path?: string;
  domain?: string;
  secure?: boolean;
  sameSite?: 'Strict' | 'Lax' | 'None';
} = {}): void {
  try {
    let cookieString = `${name}=${value}`;
    
    if (options.expires) {
      cookieString += `; expires=${options.expires.toUTCString()}`;
    }
    
    if (options.maxAge !== undefined) {
      cookieString += `; max-age=${options.maxAge}`;
    }
    
    if (options.path) {
      cookieString += `; path=${options.path}`;
    }
    
    if (options.domain) {
      cookieString += `; domain=${options.domain}`;
    }
    
    if (options.secure) {
      cookieString += `; secure`;
    }
    
    if (options.sameSite) {
      cookieString += `; samesite=${options.sameSite}`;
    }
    
    document.cookie = cookieString;
  } catch (error) {
    console.error('设置Cookie失败:', error);
  }
}

/**
 * 删除Cookie
 * @param name Cookie名称
 * @param path Cookie路径
 */
function deleteCookie(name: string, path: string = '/'): void {
  try {
    document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}`;
  } catch (error) {
    console.error('删除Cookie失败:', error);
  }
}

/**
 * HTTP请求配置
 */
interface RequestConfig {
  method: 'GET' | 'POST' | 'PUT' | 'DELETE';
  headers?: Record<string, string>;
  body?: any;
  timeout?: number;
}

/**
 * 发起HTTP请求的通用方法
 */
async function request<T>(url: string, config: RequestConfig): Promise<ApiResponse<T>> {
  const { method, headers = {}, body, timeout = REQUEST_TIMEOUT } = config;
  
  // 设置默认请求头
  const defaultHeaders: Record<string, string> = {
    'Content-Type': 'application/json',
    ...headers
  };

  // 从Cookie中获取token并添加到请求头
  const token = getCookie(COOKIE_NAMES.ACCESS_TOKEN);
  if (token) {
    defaultHeaders['Authorization'] = `Bearer ${token}`;
  }

  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);

    // 创建重试函数
    const retryRequest = () => {
      return fetch(url, {
        method,
        headers: defaultHeaders,
        body: body ? JSON.stringify(body) : undefined,
        signal: controller.signal,
        credentials: 'include' // 确保发送Cookie
      });
    };

    let response = await retryRequest();
    
    // 如果是401未授权，尝试刷新token
    if (response.status === 401) {
      // 如果是刷新token的请求失败，直接登出
      if (url.includes('/api/auth/refresh')) {
        clearUserData();
        throw new Error('Token已过期，请重新登录');
      }
      
      // 尝试刷新token
      const newToken = await refreshToken();
      if (newToken) {
        // 刷新成功，重试原始请求
        response = await retryRequest();
      } else {
        // 刷新失败，登出用户
        clearUserData();
        throw new Error('Token已过期，请重新登录');
      }
    }

    clearTimeout(timeoutId);

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const result = await response.json();
    return result;
  } catch (error) {
    console.error('API请求失败:', error);
    throw error;
  }
}

// ============= 短信验证码相关 =============

/**
 * 发送短信验证码
 * @param params 发送短信请求参数
 * @returns Promise<ApiResponse<void>>
 */
export async function sendSmsCode(params: SendSmsRequest): Promise<ApiResponse<void>> {
  return request<void>(`${API_BASE_URL}/send-sms`, {
    method: 'POST',
    body: params
  });
}

/**
 * 短信验证码登录
 * @param params 短信登录请求参数
 * @returns Promise<ApiResponse<SmsLoginResponse>>
 */
export async function smsLogin(params: SmsLoginRequest): Promise<ApiResponse<SmsLoginResponse>> {
  const response = await request<SmsLoginResponse>(`${API_BASE_URL}/sms-login`, {
    method: 'POST',
    body: params
  });

  // 登录成功后保存用户信息到本地存储（token已通过Cookie设置）
  if (response.success && response.data) {
    localStorage.setItem('userInfo', JSON.stringify(response.data.userInfo));
  }

  return response;
}

// ============= 传统登录相关 =============

/**
 * 用户名密码登录
 * @param params 登录请求参数
 * @returns Promise<ApiResponse<LoginResponse>>
 */
export async function login(params: LoginRequest): Promise<ApiResponse<LoginResponse>> {
  const response = await request<LoginResponse>(`${API_BASE_URL}/login`, {
    method: 'POST',
    body: params
  });

  // 登录成功后保存用户信息到本地存储（token已通过Cookie设置）
  if (response.success && response.data) {
    localStorage.setItem('userInfo', JSON.stringify(response.data.userInfo));
  }

  return response;
}

/**
 * 用户登出
 * @returns Promise<ApiResponse<void>>
 */
export async function logout(): Promise<ApiResponse<void>> {
  try {
    const response = await request<void>(`${API_BASE_URL}/logout`, {
      method: 'POST'
    });

    // 清除本地存储的用户信息和Cookie中的token
    clearUserData();

    return response;
  } catch (error) {
    // 即使请求失败也要清除本地数据
    clearUserData();
    throw error;
  }
}

// ============= 密码管理 =============

/**
 * 设置密码
 * @param params 设置密码请求参数
 * @returns Promise<ApiResponse<void>>
 */
export async function setPassword(params: SetPasswordRequest): Promise<ApiResponse<void>> {
  return request<void>(`${API_BASE_URL}/set-password`, {
    method: 'POST',
    body: params
  });
}

// ============= 令牌管理 =============

/**
 * 刷新访问令牌
 * @param refreshToken 刷新令牌
 * @returns Promise<ApiResponse<RefreshTokenResponse>>
 */
export async function refreshToken(refreshToken?: string): Promise<string | null> {
  // 如果没有传入refreshToken，从Cookie中获取
  const token = refreshToken || getCookie(COOKIE_NAMES.REFRESH_TOKEN);
  
  if (!token) {
    return null;
  }

  try {
    const response = await fetch(`${API_BASE_URL}/refresh`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ refreshToken: token }),
      credentials: 'include' // 确保发送Cookie
    });

    if (response.ok) {
      const result = await response.json();
      if (result.success) {
        // 刷新成功后token会通过Cookie自动更新，无需手动处理
        return result.data?.accessToken || null;
      }
    }
    
    return null;
  } catch (error) {
    console.error('刷新令牌失败:', error);
    return null;
  }
}

// ============= 可用性检查 =============

/**
 * 检查用户名是否可用
 * @param username 用户名
 * @returns Promise<ApiResponse<CheckUsernameResponse>>
 */
export async function checkUsername(username: string): Promise<ApiResponse<CheckUsernameResponse>> {
  return request<CheckUsernameResponse>(`${API_BASE_URL}/check-username?username=${encodeURIComponent(username)}`, {
    method: 'GET'
  });
}

/**
 * 检查手机号是否已存在
 * @param phone 手机号
 * @returns Promise<ApiResponse<CheckPhoneResponse>>
 */
export async function checkPhone(phone: string): Promise<ApiResponse<CheckPhoneResponse>> {
  return request<CheckPhoneResponse>(`${API_BASE_URL}/check-phone?phone=${encodeURIComponent(phone)}`, {
    method: 'GET'
  });
}

// ============= 工具函数 =============

/**
 * 清除用户数据
 */
export function clearUserData(): void {
  // 清除localStorage中的用户信息
  localStorage.removeItem('userInfo');
  
  // 清除Cookie中的token
  deleteCookie(COOKIE_NAMES.ACCESS_TOKEN);
  deleteCookie(COOKIE_NAMES.REFRESH_TOKEN);
}

/**
 * 获取当前用户信息（从服务器）
 * 调用后端API获取最新的用户信息
 * 
 * @returns {Promise<any>} 用户信息Promise
 * @throws {Error} 获取失败时抛出错误
 * @author ltx
 * @date 2024-12-19
 */
export async function getCurrentUserFromServer(): Promise<any> {
  try {
    const response = await request<any>(`${API_BASE_URL}/current`, {
      method: 'GET'
    });

    if (response.success && response.data) {
      // 将用户信息保存到localStorage
      localStorage.setItem('userInfo', JSON.stringify(response.data));
      return response.data;
    } else {
      throw new Error(response.message || '获取用户信息失败');
    }
  } catch (error) {
    console.error('从服务器获取用户信息失败:', error);
    throw error;
  }
}

/**
 * 获取当前用户信息
 * 优先从localStorage获取，如果不存在则从服务器获取
 * 
 * @returns {Promise<any>} 用户信息Promise
 * @author ltx
 * @date 2024-12-19
 */
export async function getCurrentUser(): Promise<any> {
  try {
    console.log('开始获取用户信息...');
    
    // 首先检查是否有token
    const token = getCookie(COOKIE_NAMES.ACCESS_TOKEN) || localStorage.getItem('token');
    console.log('Token存在:', !!token);
    
    if (!token) {
      console.log('没有找到token，用户未登录');
      return null;
    }

    // 尝试从localStorage获取userInfo（注意键名是userInfo而不是userInfo）
    const localUserInfo = localStorage.getItem('userInfo');
    console.log('localStorage中的userInfo:', localUserInfo);
    
    if (localUserInfo) {
      try {
        const parsedUserInfo = JSON.parse(localUserInfo);
        console.log('成功解析本地用户信息:', parsedUserInfo);
        return parsedUserInfo;
      } catch (error) {
        console.error('解析本地用户信息失败:', error);
        // 清除损坏的数据
        localStorage.removeItem('userInfo');
      }
    }

    console.log('本地没有用户信息，尝试从服务器获取...');
    // 如果本地没有，从服务器获取
    return await getCurrentUserFromServer();
  } catch (error) {
    console.error('获取用户信息失败:', error);
    return null;
  }
}

/**
 * 检查是否已登录
 * @returns 是否已登录
 */
export function isLoggedIn(): boolean {
  const token = getCookie(COOKIE_NAMES.ACCESS_TOKEN);
  return !!token;
}

/**
 * 获取访问令牌
 * @returns 访问令牌或null
 */
export function getAccessToken(): string | null {
  return getCookie(COOKIE_NAMES.ACCESS_TOKEN);
}

/**
 * 获取刷新令牌
 * @returns 刷新令牌或null
 */
export function getRefreshToken(): string | null {
  return getCookie(COOKIE_NAMES.REFRESH_TOKEN);
}

// ============= 验证码相关工具 =============

/**
 * 验证手机号格式
 * @param phone 手机号
 * @returns 是否有效
 */
export function validatePhone(phone: string): boolean {
  const phoneRegex = /^1[3-9]\d{9}$/;
  return phoneRegex.test(phone);
}

/**
 * 验证短信验证码格式
 * @param code 验证码
 * @returns 是否有效
 */
export function validateSmsCode(code: string): boolean {
  const codeRegex = /^\d{6}$/;
  return codeRegex.test(code);
}

/**
 * 验证密码强度
 * @param password 密码
 * @returns 是否符合要求
 */
export function validatePassword(password: string): boolean {
  // 密码长度至少8位，包含字母和数字
  const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$/;
  return passwordRegex.test(password);
}

// ============= 错误处理 =============

/**
 * API错误类
 */
export class ApiError extends Error {
  public code: number;
  public details?: any;

  constructor(code: number, message: string, details?: any) {
    super(message);
    this.name = 'ApiError';
    this.code = code;
    this.details = details;
  }
}

/**
 * 处理API响应错误
 * @param response API响应
 */
export function handleApiError(response: ApiResponse<any>): void {
  if (!response.success) {
    throw new ApiError(response.code, response.message, response.data);
  }
}

// ============= 导出常量 =============

export { SmsType };
export { getCookie };
export const SMS_CODE_LENGTH = 6;
export const SMS_CODE_EXPIRE_MINUTES = 5;
export const SEND_FREQUENCY_LIMIT_SECONDS = 60;